package org.chen.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.chen.enu.CommentFieldType;
import org.chen.exception.ServiceException;
import org.chen.mapper.CommentFieldPatternMapper;
import org.chen.model.CommentFieldPattern;
import org.chen.service.ICommentFieldPatternService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CommentFieldPatternServiceImpl extends ServiceImpl<CommentFieldPatternMapper, CommentFieldPattern> implements ICommentFieldPatternService {
    private static final String PATTERN_CACHE_KEY = "comment:pattern:";
    private static final long CACHE_EXPIRE_TIME = 24; // 24小时过期

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    // 默认规则模板
    public static final Map<CommentFieldType, List<String>> DEFAULT_PATTERNS = new HashMap<>() {{
        put(CommentFieldType.COMMENT, Arrays.asList(
                "comment",
                "message",
                "content",
                "text"
        ));
        put(CommentFieldType.AUTHOR, Arrays.asList(
                "author",
                "name",
                "nickname",
                "username"
        ));
        put(CommentFieldType.EMAIL, Arrays.asList(
                "email",
                "mail",
                "e-mail"
        ));
        put(CommentFieldType.URL, Arrays.asList(
                "url",
                "website",
                "site",
                "link"
        ));
    }};

    /**
     * 获取某个字段类型的所有匹配规则
     */
    public List<String> getPatterns(CommentFieldType fieldType) {
        String cacheKey = PATTERN_CACHE_KEY + fieldType.name();

        // 尝试从缓存获取
        String cachedPatterns = redisTemplate.opsForValue().get(cacheKey);
        if (cachedPatterns != null) {
            try {
                return objectMapper.readValue(cachedPatterns,
                        new TypeReference<List<String>>() {});
            } catch (Exception e) {
                log.error("解析缓存的匹配规则失败", e);
            }
        }

        // 从数据库获取
        List<String> patterns = this.lambdaQuery()
                .eq(CommentFieldPattern::getFieldType, fieldType.name())
                .eq(CommentFieldPattern::getIsEnabled, true)
                .select(CommentFieldPattern::getPattern)
                .list()
                .stream()
                .map(CommentFieldPattern::getPattern)
                .collect(Collectors.toList());

        // 如果数据库也没有，使用默认规则
        if (patterns.isEmpty() && DEFAULT_PATTERNS.containsKey(fieldType)) {
            patterns = DEFAULT_PATTERNS.get(fieldType);
        }

        // 存入缓存
        try {
            String patternsJson = objectMapper.writeValueAsString(patterns);
            redisTemplate.opsForValue().set(cacheKey, patternsJson,
                    CACHE_EXPIRE_TIME, TimeUnit.HOURS);
        } catch (Exception e) {
            log.error("缓存匹配规则失败", e);
        }

        return patterns;
    }

    /**
     * 刷新缓存
     */
    public void refreshCache(CommentFieldType fieldType) {
        redisTemplate.delete(PATTERN_CACHE_KEY + fieldType.name());
        getPatterns(fieldType);  // 重新加载缓存
    }

    /**
     * 刷新所有缓存
     */
    public void refreshAllCache() {
        Set<String> keys = redisTemplate.keys(PATTERN_CACHE_KEY + "*");
        if (!keys.isEmpty()) {
            redisTemplate.delete(keys);
        }

        // 重新加载所有类型的缓存
        for (CommentFieldType fieldType : CommentFieldType.values()) {
            getPatterns(fieldType);
        }
    }

    /**
     * 获取规则列表
     */
    public IPage<CommentFieldPattern> getPatternList(Page<CommentFieldPattern> page, String fieldType) {
        LambdaQueryWrapper<CommentFieldPattern> wrapper = new LambdaQueryWrapper<>();

        // 添加字段类型过滤
        if (StringUtils.hasText(fieldType)) {
            wrapper.eq(CommentFieldPattern::getFieldType, fieldType);
        }

        // 按更新时间倒序
        wrapper.orderByDesc(CommentFieldPattern::getUpdateTime);

        return this.page(page, wrapper);
    }

    /**
     * 添加规则
     */
    @Transactional(rollbackFor = Exception.class)
    public void addPattern(CommentFieldPattern pattern) {
        // 验证字段类型
        validateFieldType(pattern.getFieldType());

        pattern.setCreateTime(LocalDateTime.now());
        pattern.setUpdateTime(LocalDateTime.now());

        // 保存到数据库
        this.save(pattern);

        // 刷新缓存
        refreshCache(CommentFieldType.valueOf(pattern.getFieldType()));
    }

    /**
     * 更新规则
     */
    @Transactional(rollbackFor = Exception.class)
    public void updatePattern(CommentFieldPattern pattern) {
        // 验证字段类型
        validateFieldType(pattern.getFieldType());

        // 检查规则是否存在
        CommentFieldPattern existingPattern = this.getById(pattern.getId());
        if (existingPattern == null) {
            throw new ServiceException("规则不存在");
        }

        pattern.setUpdateTime(LocalDateTime.now());

        // 更新数据库
        this.updateById(pattern);

        // 刷新缓存
        refreshCache(CommentFieldType.valueOf(pattern.getFieldType()));
        // 如果字段类型发生变化，也刷新原字段类型的缓存
        if (!pattern.getFieldType().equals(existingPattern.getFieldType())) {
            refreshCache(CommentFieldType.valueOf(existingPattern.getFieldType()));
        }
    }

    /**
     * 删除规则
     */
    @Transactional(rollbackFor = Exception.class)
    public void deletePattern(Long id) {
        // 获取规则信息
        CommentFieldPattern pattern = this.getById(id);
        if (pattern == null) {
            throw new ServiceException("规则不存在");
        }

        // 删除数据库记录
        this.removeById(id);

        // 刷新缓存
        refreshCache(CommentFieldType.valueOf(pattern.getFieldType()));
    }

    /**
     * 验证字段类型
     */
    private void validateFieldType(String fieldType) {
        try {
            CommentFieldType.valueOf(fieldType);
        } catch (IllegalArgumentException e) {
            throw new ServiceException("无效的字段类型: " + fieldType);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDeletePatterns(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new ServiceException("请选择要删除的规则");
        }

        // 获取要删除的规则信息，用于刷新缓存
        List<CommentFieldPattern> patterns = this.listByIds(ids);

        // 删除数据库记录
        this.removeByIds(ids);

        // 刷新受影响的缓存
        Set<String> affectedTypes = patterns.stream()
                .map(CommentFieldPattern::getFieldType)
                .collect(Collectors.toSet());

        for (String type : affectedTypes) {
            refreshCache(CommentFieldType.valueOf(type));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchUpdateStatus(List<Long> ids, Boolean enabled) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new ServiceException("请选择要操作的规则");
        }

        // 批量更新状态
        LocalDateTime now = LocalDateTime.now();
        List<CommentFieldPattern> patterns = ids.stream()
                .map(id -> {
                    CommentFieldPattern pattern = new CommentFieldPattern();
                    pattern.setId(id);
                    pattern.setIsEnabled(enabled);
                    pattern.setUpdateTime(now);
                    return pattern;
                })
                .collect(Collectors.toList());

        this.updateBatchById(patterns);

        // 获取完整的规则信息，用于刷新缓存
        List<CommentFieldPattern> fullPatterns = this.listByIds(ids);

        // 刷新受影响的缓存
        Set<String> affectedTypes = fullPatterns.stream()
                .map(CommentFieldPattern::getFieldType)
                .collect(Collectors.toSet());

        for (String type : affectedTypes) {
            refreshCache(CommentFieldType.valueOf(type));
        }
    }
}
